package fr.babos.graphic.components.controls.text 
{
	import flash.events.Event;
	import flash.geom.Matrix;
	import flash.text.StyleSheet;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;
	import flash.text.TextFormat;
	import flash.text.TextFormatAlign;
	import flash.text.TextLineMetrics;
	import fr.babos.graphic.components.base.ResizableComponent;
	import fr.babos.utils.ScreenUtils;
	
	/**
	 * @author ZoulouX
	 */
	public class TextBase extends ResizableComponent 
	{
		/**
		 * La limite du scale pour passer en matrice
		 */
		static public var SCALE_LIMIT				:Number 					= 1;
		
		/**
		 * Le facteur sur le scale lorsqu'on est au dessus de la limit
		 */
		static public var SCALE_FACTOR				:Number 					= .75;
		
		
		/**
		 * Le texteField qui va afficher le texte
		 */
		protected var _textField					:TextField;
		
		/**
		 * Taille automatique du composant selon le contenu
		 */
		protected var _autoSize						:Boolean					= true;
		
		/**
		 * Multiligne
		 */
		protected var _multiline					:Boolean					= false;
		
		
		/**
		 * Le textField
		 */
		public function get textField ():TextField { return _textField; }
		
		/**
		 * Taille automatique du composant selon le contenu
		 */
		public function get autoSize ():Boolean { return _autoSize; }
		public function set autoSize (value:Boolean):void
		{
			if (_autoSize != value)
			{
				// Enregistrer
				_autoSize = value;
				
				// Actualiser l'autosize
				updateAutoSize();
				
				// Actualiser la taille
				resized();
			}
		}
		
		/**
		 * Multiligne
		 */
		public function get multiline ():Boolean { return _multiline; }
		public function set multiline (value:Boolean):void 
		{
			if (_multiline != value)
			{
				// Enregistrer
				_multiline = value;
				
				// Utiliser toute la largeur ou non
				_textField.wordWrap = _multiline;
				_textField.multiline = _multiline;
				
				// Actualiser l'autosize
				updateAutoSize();
				
				// Actualiser
				resized();
			}
		}
		
		/**
		 * La valeur du champs texte
		 */
		public function get value ():String { return _textField.text; }
		public function set value (value:String):void 
		{
			// Enregistrer le texte
			_textField.text = value;
			
			// Actualiser la taille
			resized();
		}
		
		/**
		 * La transparence
		 */
		override public function get alpha ():Number { return _textField.alpha; }
		override public function set alpha (value:Number):void
		{
			_textField.alpha = value;
		}
		
		
		/**
		 * Le constructeur
		 */
		public function TextBase ()
		{
			// Construire le textField
			buildTextField();
		}
		
		/**
		 * Construire le textField
		 */
		protected function buildTextField ():void
		{
			// Créer le textField
			_textField = new TextField();
			_textField.width = 0;
			_textField.height = 0;
			
			// Le configurer
			_textField.mouseWheelEnabled = false;
			
			// L'ajouter
			addChild(_textField);
		}
		
		/**
		 * Initialisation
		 */
		override public function init ():void
		{
		}
		
		public function enableCAB ():void
		{
			// --ICI-- CACHE AS BITMAP DISABLED ON TEXTFIELDS
			//return;
			
			// --ICI-- CACHE AS BITMAP MATRIX DISABLED ON TEXTFIELDS
			
			
			// La matrice que l'on va utiliser pour le CABM
			var scaleMatrix:Matrix;
			
			// Si on a une transformation 3D
			//if (_textField.transform.matrix3D != null)
			//{
				// Créer une matrice
				scaleMatrix = new Matrix();
				
				// Récupérer le scale de l'écran
				var screenScale:Number = ScreenUtils.getRatioForStage(stage);
				
				// Appliquer ce ratio à la matrice
				scaleMatrix.scale(screenScale, screenScale);
			//}
			//else
			//{
				// Récupérer la matrice depuis la displayList
				//scaleMatrix = _textField.transform.concatenatedMatrix.clone();
			//}
			
			// Récupérer le facteur d'échelle
			var scaleFactor:Number = scaleMatrix.a;
			
			// S'il est supérieur à la densité par défaut
			if (scaleFactor > SCALE_LIMIT)
			{
				// On le réduit en le limitant à 1
				scaleFactor = Math.max(1, scaleFactor * SCALE_FACTOR);
				
				// On l'applique sur la matrice
				scaleMatrix.a = scaleMatrix.d = scaleFactor;
				
				// Et on applique la matrice sur le textField
				_textField.cacheAsBitmapMatrix = scaleMatrix;
			}
			
			// Activer le stockage bitmap
			_textField.cacheAsBitmap = true;
		}
		
		/**
		 * Bordure sur le texte
		 */
		public function border (pBorder:Boolean, pBorderColor:Number = 0x000000):TextBase
		{
			// Appliquer
			_textField.border = pBorder;
			_textField.borderColor = pBorderColor;
			
			// Méthode chaînable
			return this;
		}
		
		/**
		 * Définir le format du texte
		 * @param	pFormat : Le format
		 * @param	pStart : -1 pour tout
		 * @param	pEnd : -1 pour tout
		 */
		public function format (pFormat:TextFormat, pStart:int = -1, pEnd:int = -1):TextBase
		{
			// Actualiser l'autosize
			updateAutoSize();
			
			// Appliquer le default sur le textField si on n'a pas de position ni de styleSheet
			if (pStart == -1 && pEnd == -1 && _textField.styleSheet == null)
				_textField.defaultTextFormat = pFormat;
			
			// Appliquer sur le textField
			_textField.setTextFormat(pFormat, pStart, pEnd);
			
			// Redimensionné
			resized();
			
			// Méthode chaînable
			return this;
		}
		
		/**
		 * Définir le style du texte
		 * @param	pStyle : Le style
		 */
		public function style (pStyle:StyleSheet):TextBase
		{
			// Appliquer sur le textField
			_textField.styleSheet = pStyle;
			
			// Méthode chaînable
			return this;
		}
		
		/**
		 * Définir l'affichage de la font
		 */
		public function fontRender (pEmbedFont:Boolean, pAntiAliasType:String):TextBase
		{
			// Appliquer sur le texteField
			_textField.embedFonts = pEmbedFont;
			
			// --ICI-- Toujours activer le cache as bitmap
			if (pEmbedFont)
				enableCAB();
			
			if (pAntiAliasType != null && pAntiAliasType != "")
				_textField.antiAliasType = pAntiAliasType;
			
			// Méthode chaînable
			return this;
		}
		
		/**
		 * Actualiser l'autosize
		 */
		protected function updateAutoSize ():void
		{
			if (_autoSize)
			{
				_textField.autoSize = TextFieldAutoSize.LEFT;
			}
			else
			{
				_textField.autoSize = TextFieldAutoSize.NONE;
			}
		}
		
		/**
		 * Définir le textSkin sur ce textBase
		 */
		public function textSkin (pTextSkin:TextSkin):TextBase
		{
			// Définir le format / style / rendu de font
			fontRender(pTextSkin.embedFonts, pTextSkin.antiAliasType);
			format(pTextSkin.textFormat);
			style(pTextSkin.styleSheet);
			
			// Méthode chaînable
			return this;
		}
		
		/**
		 * Définir le texte affiché (pas d'HTML)
		 * @param	pValue : Le texte à afficher
		 */
		public function text (pValue:String):TextBase
		{
			if (pValue != null && _textField.text != pValue)
			{
				// Appliquer
				_textField.text = pValue;
				
				// Actualiser la taille
				resized();
			}
			
			// Méthode chaînable
			return this;
		}
		
		/**
		 * Ajouter du texte (pas d'HTML)
		 * @param	pValue : Le texte à ajouter
		 */
		public function append (pValue:String):TextBase
		{
			// Appliquer
			_textField.appendText(pValue);
			
			// Actualiser la taille
			resized();
			
			// Méthode chaînable
			return this;
		}
		
		/**
		 * Définir le texte HTML affiché
		 * @param	pValue : Le texte HTML à afficher
		 */
		public function html (pValue:String):TextBase
		{
			if (pValue != null && _textField.htmlText != pValue)
			{
				// Appliquer
				_textField.htmlText = pValue;
				
				// Actualiser la taille
				resized();
			}
			
			// Méthode chaînable
			return this;
		}
		
		/**
		 * Redimensionnement
		 */
		override protected function resized ():void
		{
			// Si on est en taille automatique
			if (_autoSize)
			{
				// Si on est en multiligne
				if (_multiline)
				{
					// Imposer la largeur
					if (_textField.width != _localWidth)
					{
						_textField.width = _localWidth;
					}
					
					// Si la hauteur est différente
					if (_localHeight != _textField.height)
					{
						// On spécifie la hauteur
						height = _textField.height;
					}
				}
				else
				{
					// Si la taille du composant est différente de la taille du texte
					if (_localWidth != _textField.width || _localHeight != _textField.height)
					{
						// La taille du composant est selon le texte
						size(_textField.width, _textField.height);
					}
				}
			}
			else
			{
				// Appliquer la taille du textField à la taille du composant
				if (_textField.width != _localWidth)
				{
					_textField.width = _localWidth;
				}
				
				// Si on a une hauteur
				if (_localHeight >= 0 || _localHeight < 0)
				{
					// On applique la taille du textField par rapport au composant
					if (_textField.height != _localHeight)
						_textField.height = _localHeight;
				}
				
				// Si on est sur une ligne
				else if (!_multiline)
				{
					// On récupère les mesures de la première ligne
					var metrics:TextLineMetrics = _textField.getLineMetrics(0);
					
					// On applique la hauteur au textField
					if (_textField.height != metrics.height)
					{
						_textField.height = metrics.height;
					}
					
					// Et au composant
					if (_localHeight != _textField.height)
					{
						_localHeight = _textField.height;
					}
				}
			}
		}
	}
}